/****************************************************************
Christian Klugesherz
Novembre 2014
Programme de gestion thermostatique

Based  : 
     https://learn.adafruit.com/wifi-weather-station-arduino-cc3000/connecting-the-cc3000-breakout-board
     http://arduino.cc/en/Tutorial/WebServer
     https://learn.adafruit.com/adafruit-cc3000-wifi-and-xively/arduino-sketch
     http://i-arduino.blogspot.fr/p/iarduino-tutorial.html
-----------------------------------------------------------------

Arduino PIN

+5V       VCC or +5V      5V
GND        GND             GND

DIGITAL

  CC3000      
    Uno Pin    CC3000 Board    Function
    3          INT             Interrupt		(CC3000)
    4          SD_CS           SD Chip Select		(SD)
    5          EN              VBAT EN Module 		(CC3000)
   10         CS              SPI Chip Select 		(CC3000)
   11         MOSI            SPI MOSI			(SD/CC3000)
   12         MISO            SPI MISO			(SD/CC3000)
   13         SCK             SPI Clock 		(SD/CC3000)

  RS232
    0      RX
    1      TX

  Thermostat Control: Out
    8

  DHT11 sensor: In
    7

  Free 
    2
    6
    9

ANALOG INPUT
  LM35
   0

  Free
   1
   2
   3
   4
   5

****************************************************************/
#include <Adafruit_CC3000.h>
#include <SPI.h>
#include <avr/wdt.h>
#include "DHT.h"
//#include "utility/debug.h"
//#include "utility/socket.h" 

//------------------------------------------------------------------------------------------
// ----------------------------------------DEFINE------------------------------------------- 
//------------------------------------------------------------------------------------------
#define DEBUG 1

// CC3000
#define ADAFRUIT_CC3000_IRQ   3 
#define ADAFRUIT_CC3000_VBAT  5
#define ADAFRUIT_CC3000_CS    10

// WLAN
#define WLAN_SSID       "NETGEAR-1"  
//#define WLAN_SSID       "Freebox-Cave"  
#define WLAN_PASS       "377A2D0C33"

#define WLAN_SECURITY   WLAN_SEC_WPA2	// Security can be WLAN_SEC_UNSEC, WLAN_SEC_WEP, WLAN_SEC_WPA or WLAN_SEC_WPA2
#define LISTEN_PORT     23      	// What TCP port to listen on for connections. 

// DHT11 sensor pins
#define DHTPIN 7                 
#define DHTTYPE DHT11

// Output
#define THERMOSTAT_PIN     8  		// Output port to control thermostat

//------------------------------------------------------------------------------------------
// ----------------------------------------VARIABLES---------------------------------------- 
//------------------------------------------------------------------------------------------

/* Create CC3000 instance /Initialize Wifi Shield CC3000 */
Adafruit_CC3000 cc3000 = Adafruit_CC3000(ADAFRUIT_CC3000_CS, ADAFRUIT_CC3000_IRQ, ADAFRUIT_CC3000_VBAT,SPI_CLOCK_DIVIDER); 

/* Ethernet server instance which create a server running on our board: port to use */
Adafruit_CC3000_Server tcp_server(LISTEN_PORT);

/* DHT instance */
DHT dht(DHTPIN, DHTTYPE);

//---------------------------------------------------------------------------------------------------
//--------------------------------------------- FUNCTION --------------------------------------------
//---------------------------------------------------------------------------------------------------

/************************************************************************ 
  Convert integer + 1 decimal to string
  
  itoa_p(buffer,4,105) = "10.5"

 Example
    nb = 255  --> nb_len = 4

      indice     0 1 2 3  4
    buffer  =    2 5 . 5 \0

    nb = -255  --> nb_len = 5

      indice     0 1 2 3 4 5
    buffer  =    - 2 5 . 5 \0
 ************************************************************************/
char *itoa_p(char *buffer, short nb_len , short nb) {
  unsigned short n;
  unsigned short negate = 0;
  boolean point;
  
  for (n=0;n<nb_len;n++) {
    buffer[n] = '0';
  }
  
  if (nb < 0) {
    negate=1;
    n = -nb;
  } else {
    n = nb;
  }
  buffer[nb_len--] = '\0';
  
  point = true;    
  do {
    buffer[nb_len--] = (n % 10) + '0';
    if (point) {
      point = false;
      buffer[nb_len--] = '.';
    }
    n = n / 10;
  } while (n);
  
  if (negate) {
    buffer[nb_len--] = '-';
  }
  return &buffer[0];
}

/************************************************************************ 
   Tries to read the 6-byte MAC address of the CC3000 module
*************************************************************************/
#ifdef DEBUG
void displayMACAddress(void)
{
  uint8_t macAddress[6];
  
  if(!cc3000.getMacAddress(macAddress))  {
    Serial.println(F("Unable to retrieve MAC Address!\r\n"));
  }
  else  {
    Serial.print(F("MAC Address : "));
    cc3000.printHex((byte*)&macAddress, 6);
  }
}
#endif

/************************************************************************ 
 Tries to read the IP address and other connection details
************************************************************************/
#ifdef DEBUG
bool displayConnectionDetails(void)
{
  uint32_t ipAddress, netmask, gateway, dhcpserv, dnsserv;
  
  if(!cc3000.getIPAddress(&ipAddress, &netmask, &gateway, &dhcpserv, &dnsserv))
    {
      Serial.println(F("Unable to retrieve the IP Address!\r\n"));
      return false;
    }
  else
    {
      Serial.print(F("\nIP Addr: ")); cc3000.printIPdotsRev(ipAddress);
      Serial.print(F("\nNetmask: ")); cc3000.printIPdotsRev(netmask);
      Serial.print(F("\nGateway: ")); cc3000.printIPdotsRev(gateway);
      Serial.print(F("\nDHCPsrv: ")); cc3000.printIPdotsRev(dhcpserv);
      Serial.print(F("\nDNSserv: ")); cc3000.printIPdotsRev(dnsserv);
      Serial.println();
      return true;
    }
}
#endif

/************************************************************************ 
 Read Temperature
 ************************************************************************/
int ReadTemp(void) {
  float t;

  // Measure the temperature
  t = dht.readTemperature();
  return( (int)(t*10)); 
}

/************************************************************************ 
 Read Humidity
 ************************************************************************/
int ReadHum(void) {
  float h;

  // Measure the humidity 
  h = dht.readHumidity();
  return( (int)(h*10)); 
}

/************************************************************************ 
 ************************************************************************
 SETUP
    As we will connect and disconnect from the server every time we want to send data, 
    the setup() we will only include the initialization of the CC3000 chip, 
    and the connection to the WiFi network: 
 ************************************************************************
 ************************************************************************/
void setup(void)
{
  int i;
  
  /* UART */
  Serial.begin(115200);

  /* Initialize DHT Thermostat/humidity sensor */
  dht.begin();

  /* Initialise the shield module */
  Serial.println(F("\nInitializing CC3000 ..."));
  if (!cc3000.begin()) {
    Serial.println(F("Couldn't begin()! Check your wiring?"));
    while(1);
  }

#ifdef DEBUG
  /* Display Mac  Address */
  displayMACAddress();
#endif

  /* Delete any old connection data on the module */
  Serial.println(F("\nDeleting old connection profiles"));
  if (!cc3000.deleteProfiles()) {
    Serial.println(F("Failed!"));
    while(1);
  }

  /* Indicate to use DHCP */
  if (!cc3000.setDHCP()) {
    Serial.println(F("Failed to set DHCP!"));
    while(1);
  }

  /* Connect to Wifi Network */
  Serial.print(F("\nAttempting to connect to ")); Serial.println(WLAN_SSID);
  if (!cc3000.connectToAP(WLAN_SSID, WLAN_PASS, WLAN_SECURITY)) {
    Serial.println(F("Failed!"));
    while(1);
  }
  
  /* Wait for DHCP to complete */
  Serial.println(F("Request DHCP"));
  while (!cc3000.checkDHCP())  {
    delay(100); // ToDo: Insert a DHCP timeout!
  }  
  
#ifdef DEBUG
  // Display the IP address DNS, Gateway, etc.
  while (! displayConnectionDetails()) {
    delay(1000);
  }
#endif
  
  Serial.println(F("Wifi Connected!"));
  
  /* Start the server and start listening for connections */
  /* Server is running all the time */
  tcp_server.begin();
  Serial.println(F("Listening for connections..."));
  
  /* Indicate by LED blincking that all is working well */
  for (i=0;i<10;i++) {
    digitalWrite(THERMOSTAT_PIN, HIGH);  
    delay(50); 
    digitalWrite(THERMOSTAT_PIN, LOW);
    delay(50);
  } 
}

// ----------------------------------------------------------
// ----------------------------------------------------------
// The loop function runs over and over again forever
// ----------------------------------------------------------
// ----------------------------------------------------------
void loop(void){
  char packBuff[30] = "";
  int i = 0;
  char c;
  int temp;
  char tempc[7];

  /* We also need to keep in mind that we want the project to run continuously day after day, whatever happens. 
     So if the Arduino cannot connect or crashes when sending the data, we don't want it to freeze and do nothing anymore.
     This is why we need to use the Arduino watchdog. 
     This will basically reset the Arduino if no reset signal is received after a given delay. 
     Here, we will initialise the watchdog with the maximum delay of 8 seconds:   */
  // wdt_enable(WDTO_8S);

  // Return a reference to a client instance which connect to the server
  // De-connection must be done by the client or after a time out
  Adafruit_CC3000_ClientRef client = tcp_server.available();
  if (client) {
    i = 0;

    Serial.println("new client");
    //tcp_server.write("\n>>"); // no sense

    /* -----------------------------------------------------------------------------------------------
      Read information from the client as long as client connected
      client.available() = client sent data to server
     -----------------------------------------------------------------------------------------------*/
    while ( client.connected() ) {

      if ( client.available() ) {
	c = client.read();
	packBuff[i] = c;
	i++;
	if (c == '\n') {
	  Serial.print(packBuff);
	  i=0;
	  
	  // Control Thermostat HIGH :: If we get the message "CTH"
	  if (packBuff[0] = 'C' && packBuff[1]=='T' && packBuff[2]=='H') {
	    digitalWrite(THERMOSTAT_PIN,HIGH);    
	    Serial.println("Pin Thermostat ON");   
	  } 
	  // Control Thermostat LOW :: If we get the message "CTL"
	  else if (packBuff[0] = 'C' && packBuff[1]=='T' && packBuff[2]=='L') {
	    digitalWrite(THERMOSTAT_PIN,LOW);    
	    Serial.println("Pin Thermostat OFF");  
	  } 
	  // Read Thermostat State  :: If we get the message "RTS"
	  else if (packBuff[0] = 'R' && packBuff[1]=='T' && packBuff[2]=='S') {
	    temp = digitalRead(THERMOSTAT_PIN);
	    if (temp) {
	      Serial.println("ON");	
	      tcp_server.write("ON"); 
	    } else {
	      Serial.println("OFF");
	      tcp_server.write("OFF"); 
	    }
	  } 
	  // Read of temperature :: If we get the message "RDT"    example tempc = "10.5"
	  else if (packBuff[0] = 'R' && packBuff[1]=='D' && packBuff[2]=='T') {
	    temp = ReadTemp();
	    itoa_p(tempc,4,temp);
	    Serial.println(tempc);	
	    tcp_server.write(tempc);  
	  } 
	  // Read of humidity :: If we get the message "RDH"
	  else if (packBuff[0] = 'R' && packBuff[1]=='D' && packBuff[2]=='H') {
	    temp = ReadHum();
	    itoa_p(tempc,4,temp);
	    Serial.println(tempc);	
	    tcp_server.write(tempc);  
	  } 
	  else if (packBuff[0] = 'E' && packBuff[1]=='X' && packBuff[2]=='I' && packBuff[3]=='T') {
	    Serial.println(F("Got info to close the connection"));
	    client.close();
	  }
	  else {
	    Serial.println("Wrong command");       
	    tcp_server.write("Wrong Command\n");   
	    tcp_server.write("  CTH --> High \n"); 
	    tcp_server.write("  CTL --> Low \n"); 
	    tcp_server.write("  RTS --> Thermostat Output Status \n"); 
	    tcp_server.write("  RDT --> Read Temp \n"); 
	    tcp_server.write("  RDH --> Read Humidity \n"); 
	    tcp_server.write("  EXIT --> Close Connection \n>>"); 
	  }
	  delay(5);
	}      
      } // if ( client.available() ) -->  client sent data
    } // while ( client.connected() ) --> Client is no more connected

    Serial.println(F("Client has been deconnected "));
    Serial.println(F("Nevertheless close client "));
    client.close();
  } // if (client) 

  delay(5);

  //  disable the watchdog until the next loop(): */
  // Reset watchdog & disable
  //wdt_reset();
  //wdt_disable();
  
}
